package com.vortex.cloud.zhsw.xinyang.enums;

import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author : luhao
 * @version V1.0
 * @date Date : 2020年05月25日 19:52
 */
public interface IBaseEnum extends Serializable {
	/**
	 *  按枚举的value获取枚举实例
	 * @param enumType 枚举类型
	 * @param value 枚举值
	 * @param <T> 枚举
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> T fromValue(Class<T> enumType, int value) {
		for (T object : enumType.getEnumConstants()) {
			if (Objects.equals(value, object.getKey())) {
				return object;
			}
		}
		throw new IllegalArgumentException("No enum value " + value + " of " + enumType.getCanonicalName());
	}

	/**
	 *  不抛出异常按枚举的value获取枚举实例
	 * @param enumType 枚举类型
	 * @param value 枚举值
	 * @param <T> 枚举
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> T fromValue2(Class<T> enumType, int value) {
		for (T object : enumType.getEnumConstants()) {
			if (Objects.equals(value, object.getKey())) {
				return object;
			}
		}
		return null;
	}

	/**
	 *  按枚举的name获取枚举实例
	 * @param enumType 枚举类型
	 * @param name 枚举名称
	 * @param <T> 枚举
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> T fromName(Class<T> enumType, String name) {
		for (T object : enumType.getEnumConstants()) {
			if (Objects.equals(name, object.getValue())) {
				return object;
			}
		}
		throw new IllegalArgumentException("No enum name " + name + " of " + enumType.getCanonicalName());
	}

	/**
	 *  不抛出异常按枚举的name获取枚举实例
	 * @param enumType 枚举类型
	 * @param name 枚举名称
	 * @param <T> 返回对象
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> T fromName2(Class<T> enumType, String name) {
		for (T object : enumType.getEnumConstants()) {
			if (Objects.equals(name, object.getValue())) {
				return object;
			}
		}
		return null;
	}

	/**
	 *  比较
	 * @param t1 参数1
	 * @param t2 参数2
	 * @param <T> 枚举泛型
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> boolean equals(T t1, T t2) {
		return t1 != null && t2 != null && t1.getKey() == t2.getKey();
	}

	/**
	 * IBaseDbEnum枚举转换成map
	 * @param enumType 枚举类型
	 * @param <T> 枚举泛型
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> Map<Integer, String> toMap(Class<T> enumType) {
		Map<Integer, String> map = Maps.newHashMap();
		for (T t : enumType.getEnumConstants()) {
			if (t.isShow()) {
				map.put(t.getKey(), t.getValue());
			}
		}
		return map;
	}

	/**
	 * IBaseDbEnum枚举转换成string map
	 * @param enumType 枚举类型
	 * @param <T> 枚举泛型
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> Map<String, String> toStringMap(Class<T> enumType) {
		Map<String, String> map = Maps.newHashMap();
		for (T t : enumType.getEnumConstants()) {
			if (t.isShow()) {
				map.put(String.valueOf(t.getValue()), t.getValue());
			}
		}
		return map;
	}

	/**
	 * 获取枚举key集合
	 * @param enumType 枚举类型
	 * @param <T> 枚举泛型
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> List<Integer> getValues(Class<T> enumType) {
		List<Integer> list = Lists.newArrayList();
		for (T t : enumType.getEnumConstants()) {
			list.add(t.getKey());
		}
		return list;
	}

	/**
	 * 获取枚举的值集合
	 * @param enumType 枚举类型
	 * @param <T> 枚举泛型
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> List<String> getNames(Class<T> enumType) {
		List<String> list = Lists.newArrayList();
		for (T t : enumType.getEnumConstants()) {
			list.add(t.getValue());
		}
		return list;
	}

	/**
	 * 枚举对象key是否包含某个值
	 * @param enumType 枚举类型
	 * @param value 枚举键
	 * @param <T> 枚举类
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> boolean containsValue(Class<T> enumType, int value) {
		for (T t : enumType.getEnumConstants()) {
			if (value == t.getKey()) {
				return true;
			}
		}
		return false;
	}

	/**
	 *  枚举对象value是否包含某个值
	 * @param enumType 枚举类型
	 * @param value 枚举值
	 * @param <T> 枚举类
	 * @return 返回对象
	 */
	static <T extends IBaseEnum> boolean containsValue(Class<T> enumType, String value) {
		for (T t : enumType.getEnumConstants()) {
			if (value.equals(t.getValue()) ) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 用于显示的枚举名
	 *
	 * @return 返回值
	 */
	String getValue();

	/**
	 * 存储到数据库的枚举值
	 *
	 * @return 返回key
	 */
	@JsonValue
	int getKey();

	/**
	 * 是否展示出来
	 *
	 * @return 是否展示布尔值
	 */
	default boolean isShow() {
		return true;
	}
}
